/**
 * @author 迷途小羔羊
 * 2014-11-19
 */
module GYLite
{
	

	/**
 * @author 迷途小羔羊
 * 2014-11-19
 */


	/**MyLoader是一个loader和urlloader封装的多任务加载器*/
	export class GYLoader
	{
		private static _loader:GYLoader;
		public static getDefaultLoader():GYLoader
		{
			if(GYLoader._loader == null)
				GYLoader._loader = new GYLoader(30,30);
			return GYLoader._loader;
		}
		/**支持的解析类型1 blob 2 base64*/public static supportBlobMP3:number = 1;
		/**支持的解析类型1 blob 2 base64*/public static supportBlobWAV:number = 1;
		/**自定义压缩的音频解析类*/public static defCompressSound:any;
		/**图片*/public static TYPE_IMAGE = 0;
		/**纹理*/public static TYPE_TEX = 1;
		/**图集*/public static TYPE_ATLAS = 2;
		/**swf指定类名的资源(弃用)*/public static TYPE_SWF = 3;
		/**swf资源库(弃用)*/public static TYPE_SWFS = 4;
		/**字体(弃用)*/public static TYPE_FONT = 5;
		/**二进制*/public static TYPE_BINARY = 6;
		/**文本*/public static TYPE_TEXT = 7;
		/**xml(未启用)*/public static TYPE_XML = 8;
		/**json*/public static TYPE_JSON = 9;
		/**variables(弃用)*/public static TYPE_VARIABLES = 10;
		/**swf片段(弃用)*/public static TYPE_MOVIE = 11;
		/**js片段*/public static TYPE_JS = 12;
		/**声音文件*/public static TYPE_SOUND = 13;
		/**url资源*/public static TYPE_URL_RES = 14;

		public static imageToGPU:boolean;
		/**是否微信http请求接口优先，默认false*/public static wxreq:any;
		private static _resDict:any={};
		private static _resDataDict:any={};
		private _seqLoaderList:Array<SeqLoader>;
		private _seqURLLoaderList:Array<SeqURLLoader>;
		private _loadList:Array<LoadInfo>;
		private _urlLoadList:Array<LoadInfo>;
		private _loaderReq = new URLRequest();
		private _httpReq = new URLRequest();			
		private static _checkTime;
		private static _checkInterval;
		private static _timeId;
		/**
		 * @param loaderThreads Loader的线程数量 默认为1
		 * @param urlLoaderThreads UrlLoader的线程数量 默认为0
		 * @param 微信加载器，若存在则使用微信加载器方式加载
		 * */
		public constructor(loaderThreads=1,urlLoaderThreads=0)
		{
			let s = this;			
			if(loaderThreads > 0)
			{
				s._seqLoaderList=new Array(loaderThreads);//(loaderThreads,true);
				s._loadList=[];//new Array<LoadInfo>;
			}

			if(urlLoaderThreads > 0)
			{
				s._seqURLLoaderList=new Array(urlLoaderThreads);//(urlLoaderThreads,true);
				s._urlLoadList=[];//new Array<LoadInfo>;
			}			
		}
		private getLoader(loadInfo:LoadInfo):SeqLoader
		{
			var len:number;
			var l:SeqLoader,waitL:SeqLoader;
			var s = this;
			len=s._seqLoaderList.length;
			while(--len > -1)
			{
				l=s._seqLoaderList[len];
				if(l)
				{
					if(l.loadInfo)
					{
						if(l.loadInfo.path == loadInfo.path && l.loadInfo.bytes == loadInfo.bytes)
						{
							if(waitL)
								waitL.loadInfo=null;
							waitL=l;
							if(l.isLoading == 2)
							{
								loadInfo.content = l.loadInfo.content;
								loadInfo.callBack();
							}
							else
								l.loadInfo.addLoadInfo(loadInfo, loadInfo.thisObject);
							break;
						}
					}
					else if(waitL==null)
					{
						waitL=l;
						waitL.loadInfo = loadInfo;
					}
				}
				else
				{
					if(waitL == null)
					{
						s._seqLoaderList[len]=waitL=new SeqLoader;
						waitL.addEventListener(egret.Event.COMPLETE,s.LoadComp,s);
						waitL.addEventListener(egret.IOErrorEvent.IO_ERROR,s.LoadError,s);
						//waitL.addEventListener(ProgressEvent.PROGRESS,ProgFunc);
						waitL.loadInfo = loadInfo
					}
					break;
				}
			}
			return waitL;
		}
		private getURLLoader(loadInfo:LoadInfo):SeqURLLoader
		{
			var len:number;
			var l:SeqURLLoader,waitL:SeqURLLoader;
			var s = this;
			len=s._seqURLLoaderList.length;
			while(--len > -1)
			{
				l=s._seqURLLoaderList[len];
				if(l)
				{
					if(l.loadInfo)
					{
						if(l.loadInfo.path == loadInfo.path && loadInfo.sendType != LoadInfo.SEND_HTTP)
						{
							if(waitL)
								waitL.loadInfo=null;
							waitL=l;
							if(l.isLoading == 2)
							{
								loadInfo.content = l.loadInfo.content;
								loadInfo.callBack();
							}
							else
								l.loadInfo.addLoadInfo(loadInfo, loadInfo.thisObject);
							break;
						}
					}
					else if(waitL==null)
					{
						waitL=l;
						waitL.loadInfo = loadInfo;
					}
				}
				else
				{
					if(waitL == null)
					{
						s._seqURLLoaderList[len]=waitL=new SeqURLLoader;
						waitL.addEventListener(egret.Event.COMPLETE, s.UrlLoadComp,s);
						waitL.addEventListener(egret.IOErrorEvent.IO_ERROR, s.URLLoadError,s);
						// waitL.addEventListener(SecurityErrorEvent.SECURITY_ERROR, s.SecurityErr,s);
						waitL.addEventListener("progress", s.UrlProgFunc,s);
						waitL.loadInfo = loadInfo
					}
					break;
				}
			}
			return waitL;
		}

		/**读取bytes资源 png jpg bmp
		 * @param bytes uint8Array或者ByteArray的buffer属性
		 * @param callBackFunc 回调函数，返回参数为LoadInfo,返回后，loadInfo会自动被清理
		 * @param thisObject callBackFunc的this指向
		 * @param type 加载资源html blob类型 image(如image/png)
		 * @param mimeType blob资源 如"image/png" 图片文件 "audio/basic" 声音文件
		 * @param param 附加参数
		 * @param retainBytes 是否保留加载的文件字节数据
		 * */
		public loadBytes(bytes,callBackFunc,thisObject,type = 1,mimeType="image/png",param:any = null,retainBytes:boolean=false)
		{
			if(GYLoader._disposed)return;
			var s = this;
			var loadInfo=LoadInfo.getInstance();
			loadInfo.thisObject = thisObject;
			loadInfo.bytes=bytes;
			loadInfo.callBackFunc=callBackFunc;
			// loadInfo.progFunc=progFunc;
			loadInfo.type = type;
			loadInfo.mimeType = mimeType;
			loadInfo.sendType = LoadInfo.SEND_DATA;
			loadInfo.param = param;
			loadInfo.retainBytes = retainBytes;
			loadInfo.startTime = Date.now();
			if(GYLoader._resDict[bytes])
			{
				loadInfo.content=GYLoader._resDict[bytes];
				loadInfo.msg="加载完成！";
				callBackFunc(loadInfo);
				loadInfo.clear();
				return loadInfo;
			}
			var len;
			len=s._loadList.length;
			while(--len>-1)
			{
				if(bytes == s._loadList[len].bytes)
				{
					s._loadList[len].addLoadInfo(loadInfo, loadInfo.thisObject);
					return loadInfo;
				}
			}
			var l=s.getLoader(loadInfo);
			if(l)
			{
				if(l.isLoading == 0)
				{
					l.loadBytes(bytes);
					l.isLoading = 1;
				}
			}
			else
				s._loadList.push(loadInfo);
			return loadInfo;
		}
		/**读取GYPackager打包的资源
		 * @param bytes uint8Array或者ByteArray的buffer属性
		 * @param callBackFunc 回调函数，返回参数为CompressLoadInfo
		 * @param callBackFunc指向
		 * @param version 资源版本号
		 * @param progFunc 回调函数，返回参数为CompressLoadInfo
		 * @param param 附加参数 在CompressLoadInfo.param处返回
		 * @param retainBytes 是否保留加载的文件字节数据
		 * */
		public loadGYCompressBytes(buffer:ArrayBuffer,callBackFunc:Function,thisObject:any,version:string = null,progFunc:Function=null,param:any=null,retainBytes:boolean=false):CompressLoadInfo
		{let s = this;
			if(GYLoader._disposed)return;
			let v:string;
			let i:number,len:number,size:number;
			let path:string,cp;
			let type;
			let newBytes:GYByteArray,bytes:GYByteArray;
			let bLen:number,pos:number;
			let cpLoadInfo:CompressLoadInfo;
			let res:GYLite.ResObject;
			let correct:boolean = false;
			let v1:number,v2:number,v3:number;			 
			let vArr:string[];
			bytes = new GYByteArray(buffer);			
			if(bytes.readUTF() == "GYCompress")
			{
				cpLoadInfo = new CompressLoadInfo;
				cpLoadInfo.param = param;
				cpLoadInfo.callBackFunc = callBackFunc;
				cpLoadInfo.progFunc = progFunc;
				cpLoadInfo.thisObject = thisObject;				
				version = version == null?"":"?"+version;
				v = bytes.readUTF();
				vArr = v.split(".");
				v1 = Number(vArr[0].substr(1));
				v2 = Number(vArr[1]);
				v3 = Number(vArr[1]);
				if(v1 > 1)
				{
					pos = bytes.position;
					if(bytes.length > 4)
					{
						bytes.position = bytes.length - 4;
						size=len = bytes.readUnsignedInt();
						correct = len == bytes.length - 4;
					}
					if(!correct)
					{		
						cpLoadInfo.msg = "#1文件损坏" + len + "-" + (bytes.length - 4);
						cpLoadInfo.errorCode = 1;
						cpLoadInfo.setResCount(1,1);
						cpLoadInfo.callBack();
						return;
					}
					bytes.position = pos;
				}
				
				cpLoadInfo.errorCode = 0;
				
				len = bytes.readUnsignedInt();
				cpLoadInfo.setResCount(len,len);
				cpLoadInfo.progressInfo.push({length:len,version:v,size:size});
				if(len > 0)
				{
					for(i=0;i<len;++i)
					{
						path = bytes.readUTF() + version;
						type = bytes.readUnsignedInt();
						cp = bytes.readUTF();
						bLen = bytes.readUnsignedInt();
						newBytes = new GYByteArray;
						bytes.readBytes(newBytes,0,bLen);
						if(cp!="none")
							newBytes.uncompress(cp);
						if(type == GYLoader.TYPE_SOUND && GYLoader.defCompressSound)
						{
							res = ResObject.getInstance();
							res.type = type;
							res.res = new GYLoader.defCompressSound;
							let iSound:ISound = (<ISound>res.res);
							iSound.bytes = newBytes.buffer;
							iSound.mimeType = GYLoader.getMimeType(type, path);
							iSound.compress = cp;
							iSound.path = path;							
							res.pathKey = path;
							if(retainBytes)
							{					
								newBytes.position = 0;		
								res.param.bytes = newBytes;
							}											
							GYLoader.setRes(path,res);
							cpLoadInfo.callBack(null,path,Date.now());
						}
						else if(type == GYLoader.TYPE_ATLAS || type == GYLoader.TYPE_IMAGE || type == GYLoader.TYPE_TEX || type == GYLoader.TYPE_SOUND)
						{
							// cpLoadInfo.loadBytes(newBytes.buffer,cpLoadInfo.callBack,cpLoadInfo,type,GYLoader.getMimeType(type, path),{compress:cp}).path = path;
							cpLoadInfo.loadBytes(newBytes.buffer,type,GYLoader.getMimeType(type, path),{compress:cp,url:path},path,retainBytes);
						}							
						else if(type == GYLoader.TYPE_JSON)
						{
							res = ResObject.getInstance();
							res.type = type;
							res.res = JSON.parse(newBytes.readUTFBytes(newBytes.length));
							res.pathKey = path;
							if(retainBytes)
							{					
								newBytes.position = 0;		
								res.param.bytes = newBytes;
							}
							GYLoader.setDataRes(path,res);
							cpLoadInfo.callBack(null,path,Date.now());
						}
						else if(type == GYLoader.TYPE_TEXT || type == GYLoader.TYPE_JS)
						{
							res = ResObject.getInstance();
							res.type = type;
							res.res = newBytes.readUTFBytes(newBytes.length);
							res.pathKey = path;
							if(retainBytes)
							{					
								newBytes.position = 0;		
								res.param.bytes = newBytes;
							}
							GYLoader.setDataRes(path,res);
							cpLoadInfo.callBack(null,path,Date.now());
						}
						else if(type == GYLoader.TYPE_URL_RES)
						{
							//short-type,utf-url
							let url:string;
							let resType:number;							
							resType = newBytes.readShort();
							url = newBytes.readUTF();//url
							if(resType == GYLoader.TYPE_ATLAS || resType == GYLoader.TYPE_IMAGE || resType == GYLoader.TYPE_TEX || resType == GYLoader.TYPE_SOUND)
								cpLoadInfo.loadPath(url,resType);
							else
								cpLoadInfo.loadData(url,resType);
						}
						else
						{
							res = ResObject.getInstance();
							res.type = type;
							res.res = newBytes.buffer;
							res.pathKey = path;
							if(retainBytes)
							{					
								newBytes.position = 0;		
								res.param.bytes = newBytes;
							}
							GYLoader.setDataRes(path,res);
							cpLoadInfo.callBack(null,path,Date.now());
						}						
					}
				}
				else
				{
					cpLoadInfo.setResCount(1,1);
					cpLoadInfo.callBack();
				}				
			}
			return cpLoadInfo;
		}

		/**读取网络资源 swf png jpg bmp
		 * @param path 读取路径
		 * @param callBackFunc 回调函数，返回参数为LoadInfo,返回后，loadInfo会自动被清理
		 * @param thisObject callBackFunc的this指向
		 * @param type 加载资源类型 image(png,jpg), swf, font
		 * */
		public loadPath(path,callBackFunc,thisObject,type=0,param = null)
		{
			if(GYLoader._disposed)return;
			var s = this;
			var loadInfo=LoadInfo.getInstance();
			loadInfo.thisObject = thisObject;
			loadInfo.path=path;
			loadInfo.callBackFunc=callBackFunc;
			loadInfo.param = param;
			// loadInfo.progFunc=progFunc;
			loadInfo.type = type;
			loadInfo.sendType = LoadInfo.SEND_RES;
			loadInfo.startTime = Date.now();
			if(GYLoader._resDict[path])
			{
				loadInfo.content=GYLoader._resDict[path];
				loadInfo.msg="加载完成！";
				callBackFunc.call(loadInfo.thisObject, loadInfo);
				loadInfo.clear();
				return null;
			}
			var len;
			len=s._loadList.length;
			while(--len>-1)
			{
				if(path == s._loadList[len].path)
				{
					s._loadList[len].addLoadInfo(loadInfo, loadInfo.thisObject);
					return loadInfo;
				}
			}
			var l=s.getLoader(loadInfo);
			if(l)
			{
				if(l.isLoading == 0)
				{
					if(type == GYLoader.TYPE_SOUND)
						l.loadSound(path);
					else
						l.load(path);
					l.isLoading = 1;
				}
			}
			else
				s._loadList.push(loadInfo);
			return loadInfo;
		}
		/**取消加载，当调用loadPath加载资源时，调用此方法取消加载，此方法根据path和callBackFunc寻找此前的加载请求
		 * @param path	加载路径
		 * @param callBackFunc 加载完成的回调
		 * */
		public cancelLoadPath(path, callBackFunc, thisObject)
		{
			var len:number;
			var l:SeqLoader;
			var loadInfo:LoadInfo;
			var s = this;
			len=s._seqLoaderList.length;
			while(--len > -1)
			{
				l = s._seqLoaderList[len];
				if(l && l.loadInfo && l.loadInfo.path == path)
				{
					if(l.loadInfo.cancel(callBackFunc, thisObject))
					{
						l.cancelLockTime = Date.now();
						l.callLater(function(seqLoader){
							let sThis = this;
							seqLoader.breakLock();
							sThis.LoadNext(l);
						},s,0);
						l.loadInfo = null;
						s.LoadNext(l);
						return;
					}
				}
			}
			len = s._loadList.length;
			while(--len>-1)
			{
				loadInfo = s._loadList[len];
				if(loadInfo.path == path && loadInfo.cancel(callBackFunc, loadInfo.thisObject))
					s._loadList.splice(len,1);
			}
		}
		// private ProgFunc(e:ProgressEvent):void
		// {
		// 	var loadInfo:LoadInfo = e.currentTarget.loader.loadInfo
		// 	loadInfo.prog(e);
		// }
		private LoadError(e)
		{
			if(GYLoader._disposed)return;
			var s = this;
			var l = e.currentTarget;
			var loadInfo=l.loadInfo;
			if(loadInfo == null)return;
			loadInfo.msg="数据流错误#1";
			l.callLater(s.ErrorNext, s);
		}
		private ErrorNext(l)
		{
			var s = this;
			l.clearCallLater();
			if(l.loadInfo == null)return;
			l.loadInfo.callBack();
			l.loadInfo.clear();
			l.loadInfo=null;
			s.LoadNext(l);
		}
		private LoadComp(e)
		{
			if(GYLoader._disposed)return;
			let s = this;
			let l:SeqLoader;
			let loadInfo:LoadInfo;
			let type:number;
			let resObj:ResObject;
			l = e.currentTarget;
			loadInfo=l.loadInfo;
			if(loadInfo == null)return;
			l.isLoading = 2;
			type = loadInfo.type;
			resObj = s.getResByLoaderInfo(l);
			if(loadInfo.save)
			{
				if (loadInfo.path == null && loadInfo.type == GYLoader.TYPE_SOUND)
                    GYLoader._resDict[e.currentTarget.data.url] = resObj;
                else
					GYLoader._resDict[loadInfo.path] = resObj;
				if(loadInfo.retainBytes)
					resObj.param.bytes = new GYByteArray(loadInfo.bytes);
			}
			loadInfo.content = resObj;
			loadInfo.msg="加载完成";
			loadInfo.callBack();
			loadInfo.clear();
			l.loadInfo=null;
			s.LoadNext(l);
		}
		private getResByLoaderInfo(l:SeqLoader)
		{
			var type:number;
			var resObj:any;
			var loadInfo:GYLite.LoadInfo;			
			loadInfo = l.loadInfo;			
			type = loadInfo.type;			
			if(type == GYLoader.TYPE_ATLAS)
			{
				let result:{atlas:Atlas,atlasRect:AtlasRect,error:SysError};
				result = AtlasRender.getInstance().createAtlas(l.data.width,l.data.height,loadInfo.path,l.data,false);	
				if(result.error)				
					console.error(result.error.msg);
				resObj = result.atlas.atlasRes;				
				resObj.res = new egret.Texture();						
				(<egret.Texture>resObj.res).bitmapData = l.data;
				l.data.source = null;
			}
			else 
			{
				resObj = ResObject.getInstance();
				if(type == GYLoader.TYPE_IMAGE || type == GYLoader.TYPE_TEX)
				{
					resObj.res = new egret.Texture();
					(<egret.Texture>resObj.res).bitmapData = l.data;
					// if(loadInfo.retainBytes)
						(<egret.Texture>resObj.res).bitmapData.$deleteSource = false;
					if(GYLoader.imageToGPU && (<egret.Texture>resObj.res).bitmapData)//直接上传到gpu
						GYLite.GYSprite.stage.$displayList.renderBuffer.context.getWebGLTexture((<egret.Texture>resObj.res).bitmapData)
				}
				else
					resObj.res=l.data;
				resObj.pathKey = loadInfo.path;
				resObj.type = type;
			}
			
			return resObj;
		}
		private LoadNext(l:SeqLoader)
		{
			if(GYLoader._disposed)return;
			var s = this;
			if(s._loadList.length > 0)
			{
				var loadInfo=s._loadList.shift();
				l.loadInfo = loadInfo;
				if(l.isLoading!=1)
				{
					if(loadInfo.bytes)
						l.loadBytes(loadInfo.bytes);
					else
					{						
						if(l.loadInfo.type == GYLoader.TYPE_SOUND)
							l.loadSound(loadInfo.path);
						else
							l.load(loadInfo.path);
					}
					l.isLoading = 1;
				}
				return;
			}
		}
		/**httpSend请求
		 * @param url 请求的url
		 * @param callBackFunc 回调函数，返回参数为LoadInfo
		 * @param thisObject callBackFunc的this指向     *
		 * @param type  二进制(binary)、文本(text)、URL 编码变量(variables) 参考GYLoader常量
		 * @param method 访问方式 get 或者 post
		 * @param header 头部数据(Array[{key,value}])
		 * @param data 发送数据
		 * @param param 回调附加参数object
		 * */
		public httpSend(url:string,callBackFunc:Function, thisObject:any,type:number=7,method:string="get",header:Array<any> = null, data:any = null,contentType:string="",param:any = null)
		{
			if(GYLoader._disposed)return;
			var s = this;
			var loadInfo=LoadInfo.getInstance();

			loadInfo.path=url;
			loadInfo.callBackFunc=callBackFunc;			
			loadInfo.thisObject = thisObject;
			loadInfo.type = type;
			loadInfo.method = method;
			loadInfo.param = param;
			loadInfo.contentType = contentType;
			loadInfo.header = header;
			loadInfo.save = false;
			loadInfo.data = data;
			loadInfo.sendType = LoadInfo.SEND_HTTP;
			loadInfo.startTime = Date.now();
			var len;
			len=s._urlLoadList.length;
			while(--len>-1)
			{
				if(url == s._urlLoadList[len].path)
				{
					s._urlLoadList[len].addLoadInfo(loadInfo,loadInfo.thisObject);
					return loadInfo;
				}
			}
			var l=s.getURLLoader(loadInfo);
			if(l)
			{
				if(l.isLoading == 0)
				{
					s._httpReq.url = loadInfo.path;
					s._httpReq.method = loadInfo.method;
					s._httpReq.dataFormat = loadInfo.dataFormat;
					s._httpReq.data = loadInfo.data;
                	s._httpReq.requestHeaders = loadInfo.header;
					s._httpReq.contentType = contentType;
					l.load(s._httpReq);
					l.isLoading = 1;
				}
			}
			else
				s._urlLoadList.push(loadInfo);
			return loadInfo;
		}
		/**加载数据
		 * @param path 读取路径
		 * @param callBackFunc 回调函数，返回参数为LoadInfo
		 * @param thisObject callBackFunc的this指向
		 * @param progFunc 回调函数，返回参数为ProgressEvent
		 * @param type  二进制(binary)、文本(text)、URL 编码变量(variables)
		 * @param method 访问方式 get 或者 post
		 * */
		public loadData(path,callBackFunc, thisObject,progFunc=null,type=6,method="get",param = null)
		{
			if(GYLoader._disposed)return;
			var s = this;
			var loadInfo=LoadInfo.getInstance();

			loadInfo.path=path;
			loadInfo.callBackFunc=callBackFunc;
			loadInfo.progFunc=progFunc;
			loadInfo.thisObject = thisObject;
			loadInfo.type = type;
			loadInfo.method = method;
			loadInfo.param = param;
			loadInfo.sendType = LoadInfo.SEND_DATA;
			loadInfo.startTime = Date.now();
			if(GYLoader._resDataDict[path])
			{
				loadInfo.content=GYLoader._resDataDict[path];
				loadInfo.msg="加载完成！";
				callBackFunc.call(loadInfo.thisObject,loadInfo);
				loadInfo.clear();
				return null;
			}
			var len;
			len=s._urlLoadList.length;
			while(--len>-1)
			{
				if(path == s._urlLoadList[len].path)
				{
					s._urlLoadList[len].addLoadInfo(loadInfo,loadInfo.thisObject);
					return loadInfo;
				}
			}
			var l=s.getURLLoader(loadInfo);
			if(l)
			{
				if(l.isLoading == 0)
				{
					s._loaderReq.url=path;
					s._loaderReq.method=method;
					s._loaderReq.dataFormat = loadInfo.dataFormat;
					l.load(s._loaderReq);
					l.isLoading = 1;
				}
			}
			else
				s._urlLoadList.push(loadInfo);
			return loadInfo;
		}
		/**取消加载，当调用loadPath加载数据时，调用此方法取消加载，此方法根据path和callBackFunc寻找此前的加载请求
		 * @param path	加载路径
		 * @param callBackFunc 加载完成的回调
		 * */
		public cancelLoadData(path, callBackFunc, thisObject)
		{
			var s = this;
			var len:number;
			var l:SeqURLLoader;
			var loadInfo:LoadInfo;
			len=s._seqURLLoaderList.length;
			while(--len > -1)
			{
				l = s._seqURLLoaderList[len];
				if(l && l.loadInfo && l.loadInfo.path == path)
				{
					if(l.loadInfo.cancel(callBackFunc,thisObject))
					{
						l.cancelLockTime = Date.now();
						l.callLater(function(l){
							let sThis = this;
							l.breakLock();
							sThis.UrlLoadNext(l)
						},s,0);
						l.loadInfo = null;
						l.close();
					}
					return;
				}
			}
			len = s._urlLoadList.length;
			while(--len>-1)
			{
				loadInfo = s._urlLoadList[len];
				if(loadInfo.cancel(callBackFunc,loadInfo.thisObject))
					s._urlLoadList.splice(len,1);
			}
		}
		private UrlLoadComp(e)
		{
			if(GYLoader._disposed)return;
			var s = this;
			var l = e.currentTarget;
			var loadInfo:GYLite.LoadInfo;
			var resObj:GYLite.ResObject;			

			loadInfo =l.loadInfo;
			if(loadInfo == null)//已经终止
				return;			
			if(l.data == null || loadInfo.status >= 300 && loadInfo.status != 0)
			{
				loadInfo.msg="数据为异常！status:" + loadInfo.status + "#3";
				loadInfo.callBack();
				l.callLater(s.UrlErrorNext,s);
				return;
			}
			
			l.isLoading = 2;
			resObj = s.getResByBytes(l);
			if(loadInfo.save)
			{
				GYLoader._resDataDict[loadInfo.path]=resObj;
				if(loadInfo.retainBytes)
					resObj.param.bytes = new GYByteArray(loadInfo.bytes);
			}
			loadInfo.content = resObj;
			loadInfo.msg="加载完成！";
			loadInfo.callBack();
			loadInfo.clear();
			l.loadInfo = null;			
			s.UrlLoadNext(l);
		}
		private getResByBytes(l)
		{
			var loadInfo;
			var type;
			loadInfo = l.loadInfo;
			type = loadInfo.type;
			var resObj = ResObject.getInstance();			
			resObj.pathKey = loadInfo.path;
			resObj.type = type;
			var winURL = window["URL"] || window["webkitURL"];			
			if(type == GYLoader.TYPE_SOUND)
			{
				resObj.res = winURL.createObjectURL(l.data);
			}
			else
			{
				if(type == GYLoader.TYPE_JSON && CommonUtil.GYIs(l.data, String))
					resObj.res = JSON.parse(l.data);
				else
					resObj.res = l.data;
			}				
			return resObj;
		}
		private URLLoadError(e)
		{
			if(GYLoader._disposed)return;
			var s = this;
			var l:SeqURLLoader = e.currentTarget;
			var loadInfo=l.loadInfo;
			if(loadInfo == null)return;
			loadInfo.msg="数据流错误！#1";
			loadInfo.callBack();
			l.callLater(s.UrlErrorNext,s);
		}
		// private SecurityErr(e:SecurityErrorEvent):void
		// {
		// 	var s = this;
		// 	var l:SeqURLLoader = e.currentTarget as SeqURLLoader;
		// 	var loadInfo:LoadInfo=l.loadInfo;
		// 	loadInfo.msg="沙箱错误！#2";
		// 	loadInfo.callBack();
		// 	loadInfo.clear();
		// 	l.callLater(UrlErrorNext);
		// }
		private UrlErrorNext(l)
		{			
			var s = this;
			l.clearCallLater();
			if(l.loadInfo == null)return;
			l.loadInfo=null;
			s.UrlLoadNext(l);
		}
		private UrlProgFunc(e)
		{
			if(GYLoader._disposed)return;
			var loadInfo = e.currentTarget.loadInfo
			loadInfo.prog(e);
		}
		private UrlLoadNext(l)
		{
			if(GYLoader._disposed)return;
			var s = this;
			if(s._urlLoadList.length > 0)
			{
				var loadInfo=s._urlLoadList.shift();
				l.loadInfo = loadInfo;
				if(l.isLoading!=1)
				{
					if(loadInfo.sendType == LoadInfo.SEND_HTTP)
					{
						s._httpReq.dataFormat = loadInfo.dataFormat;
						s._httpReq.url = loadInfo.path;
						s._httpReq.method = loadInfo.method;
						s._httpReq.contentType = loadInfo.contentType;
						s._httpReq.requestHeaders = loadInfo.header;
						s._httpReq.data = loadInfo.data;
						l.load(s._httpReq);
					}
					else
					{
						s._loaderReq.dataFormat = loadInfo.dataFormat;
						s._loaderReq.url = loadInfo.path;
						s._loaderReq.method = loadInfo.method;
						s._loaderReq.contentType = loadInfo.contentType;						
						l.load(s._loaderReq);
					}					
					
					l.isLoading = 1;
					return;
				}
			}
		}
		public static getMimeType(type:number, path:string = null):string
		{			
			let arr:Array<string>;
			let ext:string;			
			if(path)
			{
				arr = path.split(".");
				ext = arr.length > 1?arr[arr.length - 1]:null;
				arr = ext.split("?");
				if(arr.length > 1)				
					ext = arr[0];				
				arr = ext.split("$");
				if(arr.length > 1)				
					ext = arr[0];				
			}
				
			if(type == GYLoader.TYPE_SOUND)
			{				
				if(ext)
					return "audio/" + ext;
				return "audio/basic";
			}
			if(ext == "jpg")
			{
				return "image/jpeg";
			}
			if(ext)
				return "image/" + ext;
			return "image/png";
		}
		public static getImageMemory():number
		{
			let total:number = 0;
			let dict:any = GYLoader._resDict;
			let resObj:ResObject;
			for(let key in dict)
			{
				resObj = dict[key];
				if(resObj.type == GYLoader.TYPE_IMAGE && resObj.pathKey.indexOf("$") == -1 || resObj.type == GYLoader.TYPE_TEX)
				{
					let img:HTMLImageElement = resObj.res.bitmapData.source;
					if(img)
						total += img.width * img.height * 4;
				}
			}
			return total;
		}
		public static getImageGPUMemory():number
		{
			let total:number = 0;
			let dict:any = GYLoader._resDict;
			let resObj:ResObject;
			for(let key in dict)
			{
				resObj = dict[key];
				if(resObj.type == GYLoader.TYPE_IMAGE && resObj.pathKey.indexOf("$") == -1 || resObj.type == GYLoader.TYPE_TEX)
				{
					total += resObj.res.textureWidth * resObj.res.textureWidth * 4;
				}
			}
			return total;
		}		
		/**设置资源回收的时间间隔，为0时不回收*/
		public static setResCheck(val)
		{			
			if(GYLoader._checkInterval > 0)
			{
				TimeManager.unRegistered(GYLoader._timeId,GYLoader.checkResUse, null);
			}
			GYLoader._checkInterval = val;
			if(val > 0)
			{
				GYLoader._checkTime = CommonUtil.loopTime;
				GYLoader._timeId = TimeManager.registered(GYLoader.checkResUse, null);
			}
		}

		public static checkResUse(sysTime)
		{			
			if(sysTime - GYLoader._checkTime < GYLoader._checkInterval)
				return;
			if(GYLoader._disposed)
			{
				GYLoader.setResCheck(-1);
				return;
			}
			GYLoader._checkTime = sysTime;
			var temp=[];
			for (var key in GYLoader._resDict)
			{
				if(GYLoader._resDict[key].count <= 0)
				{
					GYLoader._resDict[key].clear();
					temp.push(key);
				}
			}
			var len;
			len = temp.length;
			while(--len>-1)
				delete GYLoader._resDict[temp[len]];
			temp.length = 0;
			for (var key in GYLoader._resDataDict)
			{
				if(GYLoader._resDict[key].count <= 0)
				{
					GYLoader._resDict[key].clear();
					temp.push(key);
				}
			}
			len = temp.length;
			while(--len>-1)
				delete GYLoader._resDataDict[temp[len]];
			temp.length = 0;
		}
		/**获取包含key键的数据资源,假设data文件夹下面的资源，如 data/,结尾带上/，以便区分文件夹节点 
		 * @param searchKey 资源键名
		 * @param exact 是否完全匹配 默认false
		 * @param ignoreVersion 匹配忽略版本号
		*/
		public static getDataResByKey(searchKey:string, exact:boolean=false,ignoreVersion:boolean=true):Array<ResObject>
		{
			var s = this;			
			var temp=[];
			var ind:number;
			for (var key in GYLoader._resDataDict)
			{	
				let arr:string[];
				if(ignoreVersion)
				{
					arr = key.split("?");
					key = arr[0];
				}				
				ind = key.indexOf(searchKey);
				if(exact)
				{					
					if(key.substr(ind) == searchKey)
						temp.push(GYLoader._resDataDict[key]);
				}
				else if(ind == 0 || key.indexOf("/" + searchKey) > -1)
				{					
					temp.push(GYLoader._resDataDict[key]);
				}
			}
			return temp;
		}
		/**获取包含key键的资源,假设img文件夹下面的资源，如 img/,结尾带上/，以便区分文件夹节点 
		 * @param searchKey 资源键名
		 * @param exact 是否完全匹配 默认false
		*/
		public static getResByKey(searchKey:string, exact:boolean=false):Array<ResObject>
		{
			var s = this;			
			var temp=[];
			var ind:number;
			for (var key in GYLoader._resDict)
			{				
				ind = key.indexOf(searchKey);
				if(exact)
				{
					if(key.substr(ind) == searchKey)
						temp.push(GYLoader._resDataDict[key]);
				}
				else if(ind == 0 || key.indexOf("/" + searchKey) > -1)
				{					
					temp.push(GYLoader._resDict[key]);
				}
			}
			return temp;
		}	
		/**销毁资源
		 * @param resObj ResObject资源
		 * @param dictType 资源类型 默认3 媒体资源和数据 1媒体资源 2数据		 
		*/
		public static deleteRes(resObj:ResObject,dictType:number=3):void
		{
			resObj.clear();
			if(dictType & 1)
				delete GYLoader._resDict[resObj.pathKey];
			if(dictType & 2)
				delete GYLoader._resDataDict[resObj.pathKey];
		}	
		/**删除包含key键的资源,删除img文件夹下面的资源，如 img/,结尾带上/，以便区分文件夹节点, deleteKey为空则删除全部资源 
		 * @param deleteKey 资源键名
		 * @param dictType 资源类型 默认3 媒体资源和数据 1媒体资源 2数据
		 * @param fuzzy 是否模糊匹配，默认true
		*/
		public static deleteResByKey(deleteKey:string,dictType:number=3, fuzzy:boolean=true):void
		{			
			let temp:string[];
			let ind:number;
			let resObj:ResObject;			
			let len:number;
			if(dictType & 1)
			{
				if(fuzzy)
				{
					temp=[];
					for (var key in GYLoader._resDict)
					{		
						if(deleteKey == null && resObj.count <= 0)		
						{
							resObj.clear();
							temp.push(key);
						}
						else if(ind == 0 || key.indexOf("/" + deleteKey) > -1)
						{
							resObj = GYLoader._resDict[key];
							if(resObj.count <= 0)
							{
								resObj.clear();								
								temp.push(key);
							}					
						}
						
						len = temp.length;
						while(--len>-1)
							delete GYLoader._resDict[temp[len]];
						temp.length = 0;					
					}					
				}
				else
				{
					resObj = GYLoader._resDict[deleteKey];
					if(resObj.count <= 0)
					{
						resObj.clear();								
						delete GYLoader._resDict[deleteKey];
					}
				}									
			}			
			if(dictType & 2)
			{
				if(fuzzy)
				{
					temp=[];
					for (var key in GYLoader._resDataDict)
					{
						if(deleteKey == null && resObj.count <= 0)		
						{
							resObj.clear();
							temp.push(key);
						}
						else if(ind == 0 || key.indexOf("/" + deleteKey) > -1)
						{
							resObj = GYLoader._resDataDict[key];
							if(resObj.count <= 0)
							{
								resObj.clear();
								temp.push(key);
							}							
						}
					}
					len = temp.length;
					while(--len>-1)
						delete GYLoader._resDataDict[temp[len]];
					temp.length = 0;
				}
				else
				{
					resObj = GYLoader._resDataDict[deleteKey];
					if(resObj.count <= 0)
					{
						resObj.clear();								
						temp.push(key);
					}
				}
			}			
		}
		/**获取位图、动画资源
		 * @param key 资源路径，需要后缀
		 * @param aliasKey 图集资源路径，如果存在图集，则key为图集内小图名称，需要后缀
		*/
		public static getRes(key:string,aliasKey:string=null)
		{
			let res:ResObject;			
			let newKey:string;		
			if(aliasKey == null)
                res = GYLoader._resDict[key];
            else
            {
                // let arr:Array<String>;
                newKey = aliasKey + "$" + key;
				res = GYLoader._resDict[newKey];                  
                let aliasRes:GYLite.ResObject;
                if(res == null)
                {                    
					aliasRes = GYLoader._resDict[aliasKey];
					if(aliasRes && aliasRes.param.jsonRes == null)
					{
						if(GYLoader._resDict[newKey] == null)//不存在，初始化一下
						{
							res = GYLite.GYLoader.getDataRes(aliasKey.replace(".png",".json"));
							if(res)																
								AtlasRender.getInstance().inputSpriteSheet(res,aliasRes.param.atlasId);
						}						
						res = GYLoader._resDict[newKey];
					}
                }				
            }			
			return res;
		}		
		/**获取二进制数据资源*/
		public static getDataRes(val:string)
		{
			return GYLoader._resDataDict[val];
		}
		public static setRes(key:string,val:ResObject):void
		{
			if(GYLoader._resDict[key]!=null)
				(<ResObject>GYLoader._resDict[key]).clear();
			GYLoader._resDict[key] = val;
		}
		public static setDataRes(key:string,val:ResObject):void
		{
			if(GYLoader._resDataDict[key]!=null)
				(<ResObject>GYLoader._resDataDict[key]).clear();
			GYLoader._resDataDict[key] = val;
		}
		/**获取媒体资源数组*/
		public static resArray():ResObject[]
		{
			let arr:ResObject[] = [];
			for(var key in GYLoader._resDict)
			{
				arr.push(GYLoader._resDict[key]);
			}
			return arr;
		}
		/**获取数据资源数组*/
		public static dataResArray():ResObject[]
		{
			let arr:ResObject[] = [];
			for(var key in GYLoader._resDataDict)
			{
				arr.push(GYLoader._resDataDict[key]);
			}
			return arr;
		}
		/**销毁加载系统*/
		public static dispose():void
		{
			GYLoader._disposed = true;
			let resObj:ResObject;
			let dict:any = GYLite.GYLoader._resDict;
			for (var key in dict) {                              
				resObj = dict[key];
				resObj.clear();
            }
			dict = GYLite.GYLoader._resDataDict;
			for (var key in dict) {                              
				resObj = dict[key];
				resObj.clear();
            }
			GYLite.GYLoader._resDict = null;
			GYLite.GYLoader._resDataDict = null;
		}
		/**加载系统是否已销毁*/
		public static get disposed():boolean
		{
			return GYLoader._disposed;
		}
		public static _disposed:boolean;
	}

	export class SeqURLLoader extends egret.EventDispatcher
	{
		private _loadInfo:LoadInfo;
		private _intervalId:number;
		private _isLoading:number;
		private _xmlHttpRequest:any;
		private _data:any;
		private _cancelLockTime:number;
		public progressData:any;
		private _laterFunc:Function;
		private _laterObject:any;
		private _bindHandleEvent:Function;
		public constructor()
		{
			super();
			let s = this;
			s._loadInfo=null;
			s._intervalId=-1;
			s._isLoading=0;
			s._xmlHttpRequest=null;
			s._data=null;
		}
		public set loadInfo(val)
		{
			var s = this;
			if(val == null)
			{
				s._isLoading=0;
				if(s._cancelLockTime == 0)
					s.clearCallLater();
				if(s._xmlHttpRequest && GYLoader.wxreq == null)
					s._xmlHttpRequest.removeEventListener('progress', s._bindHandleEvent);
				s._bindHandleEvent = null;
				s._data = null;//清空数据放置内存滞留
				s._xmlHttpRequest = null;//清空数据放置内存滞留
				s.progressData = null;//
			}
			s._loadInfo = val;
		}
		public get loadInfo()
		{
			return this._loadInfo;
		}
		private handleEvent(e){
			let s = this;
			if(GYLoader._disposed)return;
			s.progressData = e;
			s.dispatchEventWith("progress");
		}
		public close():void
		{
			let s = this;
			if(s._xmlHttpRequest)s._xmlHttpRequest.abort();
		}
		public load(req:URLRequest)
		{var s =this;
			if(GYLoader._disposed)return;
			let wxData:any;
			let request;			
			if (GYLoader.wxreq)//优先判断微信的request
			{
				s._xmlHttpRequest = GYLoader.wxreq;
				request = s._xmlHttpRequest;
				wxData = {};
				wxData.method = req.method;
				wxData.responseType = req.dataFormat == "arraybuffer"?req.dataFormat:"text";				
				wxData.dataType = (req.dataFormat == "json" || req.dataFormat == "text")?"text":"other";
				wxData.url = req.url;
				wxData.header = {};
			}
			else if (window["XMLHttpRequest"])
			{// code for all new browsers
				s._xmlHttpRequest=new XMLHttpRequest();
				s._bindHandleEvent = s.handleEvent.bind(s);
				s._xmlHttpRequest.addEventListener('progress', s._bindHandleEvent);
			}
			else if (window["ActiveXObject"])
			{// code for IE5 and IE6
				s._xmlHttpRequest=new window["ActiveXObject"]("Microsoft.XMLHTTP");
			}
			
			request = s._xmlHttpRequest;
			if(request == null)return;
			if(!wxData)//微信sdk的
			{	
				request.open(req.method, req.url, true);
				request.responseType = req.dataFormat;//"arraybuffer";
				request.onreadystatechange = function () {
					s._loadInfo.progressInfo.push({state:request.readyState,time:Date.now()-s.loadInfo.startTime,status:request.status});
					if (request.readyState == 4) {
						var ioError = request.status!=200 && request.status!=0;
						GYLite.TimeManager.timeOut(function(ioError:boolean):void{
							if (ioError) {
								//self.dispatchEventWith(egret.IOErrorEvent.IO_ERROR);
								s.loadError();
							}
							else {
								s.loadComp();
							}
						},s,0,ioError)						
					}
				};
			}			
			
			let i,len;
			len = req.requestHeaders?req.requestHeaders.length:0;
			if(len > 0)
			{
				for(i=0;i<len;++i)
				{
					if(wxData)
						wxData.header[req.requestHeaders[i].key] = req.requestHeaders[i].value;
					else
						request.setRequestHeader(req.requestHeaders[i].key,req.requestHeaders[i].value);
				}
			}
			let sendData;
			if (req.method == "get" || !req.data) {
			}
			else if (CommonUtil.GYIs(req.data,URLVariables)) {
				if(wxData)
					wxData.header["Content-Type"] = "application/x-www-form-urlencoded";
				else
					request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
				var urlVars = req.data;
				sendData = urlVars.toString();
			}
			else if (CommonUtil.GYIs(req.data,FormData))
			{
				sendData = req.data;
			}
			else {
				if(req.contentType=="" || req.contentType == null)
				{
					if(wxData)
						wxData.header["Content-Type"] = "multipart/form-data";
					else
						request.setRequestHeader("Content-Type", "multipart/form-data");
				}				
				sendData = req.data;
			}

			if(wxData)
			{
				if(req.contentType!="" && req.contentType != null)
				wxData.header["Content-Type"] = req.contentType;
				wxData.success = s.loadComp.bind(s);
				wxData.fail = s.loadError.bind(s);
				wxData.data = sendData;
				s._xmlHttpRequest(wxData);
			}
			else
			{
				if(req.contentType!="" && req.contentType != null)
				request.setRequestHeader("Content-Type",req.contentType);				
				request.send(sendData);
			}
		}
		public get data()
		{
			return this._data;
		}
		private loadComp(res:any=null)
		{
			if(GYLoader._disposed)return;
			var s = this;
			s._data = res?res.data:s._xmlHttpRequest.response;
			s._loadInfo.status = s._xmlHttpRequest.status == null?(res && res.statusCode?res.statusCode:500):s._xmlHttpRequest.status;
			s.dispatchEvent(new egret.Event(egret.Event.COMPLETE));
		}
		private loadError(res:any = null){
			if(GYLoader._disposed)return;
			var s = this;
			s._data = null
			s.dispatchEvent(new egret.IOErrorEvent(egret.IOErrorEvent.IO_ERROR));
		}
		/**由于连续加载时，上一个失败立即使用这个loader会产生加载中断的bug，所以进行延时处理*/
		public callLater(func:Function,thisObject:any,delay:number=100)
		{
			var s = this;
			s._laterFunc = func;
			s._laterObject = thisObject;
			func = func.bind(thisObject);
			s._intervalId = setTimeout(s.laterCall.bind(s),delay);
		}
		private laterCall():void
		{let s= this;
			if(s._laterFunc!=null)
			{
				s._laterFunc.call(s._laterObject,s);
				s._laterFunc = s._laterObject = null;
			}
				
		}
		/**清理延时*/
		public clearCallLater()
		{
			var s = this;
			if(s._intervalId > -1)
			{
				clearInterval(s._intervalId);
				s._intervalId = -1;
			}
		}
		public get cancelLockTime()
		{
			return this._cancelLockTime;
		}
		public set cancelLockTime(value)
		{
			this._cancelLockTime = value;
		}
		public get isLoading()
		{
			return this._isLoading;
		}
		public set isLoading(val)
		{
			this._isLoading = val;
		}
		public breakLock()
		{var s = this;
			s._cancelLockTime = 0;
		}
		
	}

	export class SeqLoader extends egret.EventDispatcher
	{
		private _loadInfo:LoadInfo;
		private _intervalId:number;
		private _isLoading:number;
		private _imageLoader:any;
		private _soundLoader:egret.Sound;
		private _cancelLockTime:number;
		private _data:any;
		private _laterFunc:Function;
		private _laterObject:any;
		private _bytes:any;
		public constructor()
		{
			super();
			let s = this;
			s._loadInfo=null;
			s._intervalId=-1;
			s._isLoading=0;
			s._imageLoader=null;
			s._cancelLockTime = 0;
			s._data=null;
		}
		public set loadInfo(val)
		{
			var s = this;
			if(val == null)
			{
				// s.unload();
				s._isLoading=0;
				if(s._cancelLockTime == 0)
					s.clearCallLater();
				s._data=null;								
			}
			s._loadInfo = val;
		}
		public get loadInfo()
		{
			return this._loadInfo;
		}
		public get isLoading()
		{
			return this._isLoading;
		}
		public set isLoading(val)
		{
			this._isLoading = val;
		}
		public loadBytes(bytes)
		{let s = this;
			if(GYLoader._disposed)return;
			var blob;
			var url;
			s._bytes = bytes;		
			// if(s._loadInfo.type == GYLoader.TYPE_IMAGE && window["createImageBitmap"])				
			// {
			// 	s.loadBitmap(blob);
			// }
			// else
			// {
				if ((GYLoader.supportBlobMP3 == 2 && s._loadInfo.mimeType == "audio/mp3") || (GYLoader.supportBlobWAV == 2 && s._loadInfo.mimeType == "audio/wav") || egret.nativeRender)
				{				
					let str:string = egret.Base64Util.encode(bytes);				
					url = "data:"+s._loadInfo.mimeType + ";base64,"+str;
					// console.log("运行时("+egret.Capabilities.runtimeType+"):" + (s._loadInfo.path?s._loadInfo.path:(s._loadInfo.param?s._loadInfo.param.url:bytes.length)));
				}
				else
				{
					if(egret.wxgame.wx)
					{
						url = egret.wxgame.wx.env.USER_DATA_PATH + "/" + (++egret.$hashCount);
						egret.wxgame.wx.getFileSystemManager().writeFile(url,bytes,"binary");
						
					}
					else
					{
						blob = new Blob([bytes], {type: s._loadInfo.mimeType});
						url = URL.createObjectURL(blob);
					}					
					// console.log("非运行时("+egret.Capabilities.runtimeType+"):" + (s._loadInfo.path?s._loadInfo.path:(s._loadInfo.param?s._loadInfo.param.url:bytes.length)));
				}
				if(s._loadInfo.type == GYLoader.TYPE_SOUND)
					s.loadSound(url);
				else
					s.load(url);	
			// }
			
		}
		public loadSound(url:string):void
		{
			let s = this;
			if(GYLoader._disposed)return;
			s._soundLoader = new egret.Sound;
			s._soundLoader.load(url);
			s._soundLoader.addEventListener(egret.Event.COMPLETE, s.loadSoundComp,s);
			s._soundLoader.addEventListener(egret.IOErrorEvent.IO_ERROR, s.loadSoundError,s);			
		}
		private loadSoundComp(e:egret.Event):void
		{
			let s= this;
			if(GYLoader._disposed)return;
			s._data = s._soundLoader;
			s._soundLoader.removeEventListener(egret.Event.COMPLETE, s.loadSoundComp,s);
			s._soundLoader.removeEventListener(egret.IOErrorEvent.IO_ERROR, s.loadSoundError,s);			
			var url = s._data.url;			
			if (url.indexOf("blob:") == 0) {
				var winURL = window["URL"] || window["webkitURL"];
				try {
					winURL.revokeObjectURL(s._data.src);
				}
				catch (e) {
					egret.$warn(1037);
				}
			}
			s.dispatchEvent(new egret.Event(egret.Event.COMPLETE));
			s._bytes = null;			
		}
		private loadSoundError(e:egret.IOErrorEvent):void
		{
			let s= this;
			if(GYLoader._disposed)return;
			s._soundLoader.removeEventListener(egret.Event.COMPLETE, s.loadSoundComp,s);
			s._soundLoader.removeEventListener(egret.IOErrorEvent.IO_ERROR, s.loadSoundError,s);
			if(GYLoader.supportBlobMP3 == 1 && s.loadInfo.mimeType == "audio/mp3" || GYLoader.supportBlobWAV == 1 && s.loadInfo.mimeType == "audio/wav")
			{
				if(s.loadInfo.mimeType == "audio/mp3")
				{
					GYLoader.supportBlobMP3 = 2;
					console.warn("可能不支持blob格式的MP3:"+s._loadInfo.path);
				}					
				else if(s.loadInfo.mimeType == "audio/wav")
				{
					console.warn("可能不支持blob格式的WAV:" + s._loadInfo.path);
					GYLoader.supportBlobWAV = 2;
				}					
				s.loadBytes(s._bytes);
				s._bytes = null;
				return;	
			}			
			s._data = null;			
			s.dispatchEvent(new egret.IOErrorEvent(egret.IOErrorEvent.IO_ERROR));
		}
		public load(url:string)
		{var s =this;
			if(GYLoader._disposed)return;
			s._imageLoader = egret.wxgame.wx?egret.wxgame.wx.createImage():new Image();
			s._imageLoader.crossOrigin = "*";
			s._imageLoader.onload = s.loadComp.bind(s);
			s._imageLoader.onerror = s.loadError.bind(s);
			s._imageLoader.src = url;
		}
		public loadBitmap(blob:Blob):void
		{
			let s = this;		
			if(GYLoader._disposed)return;	
			window["createImageBitmap"](blob).then(s.loadBitmapComp.bind(s));	
		}
		get data()
		{
			return this._data;
		}
		private loadBitmapComp(response):void
		{
			if(GYLoader._disposed)return;
			var s = this;
			s._data = new egret.BitmapData(response);
			s._data.source.src = s._loadInfo.path;
			s.dispatchEvent(new egret.Event(egret.Event.COMPLETE));
		}
		private loadComp(e)
		{
			if(GYLoader._disposed)return;
			var s = this;
			let img = e.target;
			img.onload = null;
			img.onerror = null;		
			s._data = new egret.BitmapData(img);
			s.dispatchEvent(new egret.Event(egret.Event.COMPLETE));
			// var url = img.src;
			// if (url.indexOf("blob:") == 0) {
			// 	var winURL = window["URL"] || window["webkitURL"];
			// 	try {
			// 		winURL.revokeObjectURL(img.src);
			// 	}
			// 	catch (e) {
			// 		egret.$warn(1037);
			// 	}
			// }
		}
		private loadError(e){
			if(GYLoader._disposed)return;
			var s = this;
			let img = e.target;
			img.onload = null;
			img.onerror = null;
			s._data = null;
			s.dispatchEvent(new egret.IOErrorEvent(egret.IOErrorEvent.IO_ERROR));
		}
		/**由于连续加载时，上一个失败立即使用这个loader会产生加载中断的bug，所以进行延时处理*/
		public callLater(func:Function,thisObject:any,delay:number=100)
		{
			var s = this;
			s._laterFunc = func;
			s._laterObject = thisObject;
			s._intervalId = setTimeout(s.laterCall.bind(s),delay);
		}
		private laterCall():void
		{let s= this;
			if(s._laterFunc!=null)
				s._laterFunc.call(s._laterObject,s);
		}
		/**清理延时*/
		public clearCallLater()
		{
			var s = this;
			if(s._intervalId > -1)
			{
				clearInterval(s._intervalId);
				s._intervalId = -1;
			}
		}
		public get cancelLockTime()
		{var s = this;
			return s._cancelLockTime;
		}

		public set cancelLockTime(value)
		{var s = this;
			s._cancelLockTime = value;
		}
		public breakLock()
		{var s = this;
			s._cancelLockTime = 0;
		}
	}
	export class URLRequest{
		public method;
		public dataFormat;
		public url;
		public contentType;
		public requestHeaders;
		public data:any;
		public constructor()
		{
			let s = this;
			s.method= "GET";
			s.dataFormat = "text";
			s.url = "";
			s.contentType = "";
			s.requestHeaders = [];
		}
	}
	export class URLRequestHeader{
		public key:string;
		public value:string;
		public constructor(key,value)
		{
			let s = this;
			s.key = key;
			s.value = value;
		}
	}
	export class URLVariables{
		public variables:any;
		public constructor(source) {
			if (source === void 0) { source = null; }
			let s = this;
			s.variables = null;
			if (source !== null) {
				s.decode(source);
			}
		}
		public decode(source) {
			if (!this.variables) {
				this.variables = {};
			}
			source = source.split("+").join(" ");
			var tokens, re = /[?&]?([^=]+)=([^&]*)/g;
			while (tokens = re.exec(source)) {
				var key = decodeURIComponent(tokens[1]), val = decodeURIComponent(tokens[2]);
				//没有重复键值，直接赋值
				if ((key in this.variables) == false) {
					this.variables[key] = val;
					continue;
				}
				//有重复键值，如果已经存在数组，直接push到数组，否则创建一个新数组
				var value = this.variables[key];
				if (value instanceof Array) {
					value.push(val);
				}
				else {
					this.variables[key] = [value, val];
				}
			}
		}
		public toString() {
			if (!this.variables) {
				return "";
			}
			var variables = this.variables;
			var stringArray = [];
			for (var key in variables) {
				stringArray.push(this.encodeValue(key, variables[key]));
			}
			return stringArray.join("&");
		}
		public encodeValue(key, value) {
			if (value instanceof Array) {
				return this.encodeArray(key, value);
			}
			else {
				return encodeURIComponent(key) + "=" + encodeURIComponent(value);
			}
		}
		public encodeArray(key, value) {
			if (!key)
				return "";
			if (value.length == 0) {
				return encodeURIComponent(key) + "=";
			}
			return value.map(function (v) { return encodeURIComponent(key) + "=" + encodeURIComponent(v); }).join("&");
		}
	}
	

	export class URLLoaderDataFormat{
		public static BINARY = "binary";
		public static TEXT = "text";
		public static VARIABLES = "variables";
		public static JSON = "json";
		
	}
	
}